package com.ykj.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.ykj.dto.Result;
import com.ykj.dto.UserMsg;
import com.ykj.entity.User;
import com.ykj.mapper.UserMapper;
import com.ykj.service.UserServer;
import com.ykj.utils.ChangeBeanUtils;
import com.ykj.utils.MyUtils;
import com.ykj.utils.PasswordEncoder;
import com.ykj.utils.RegexUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.ykj.utils.RedisConstants.*;
import static com.ykj.utils.SystemConstants.USER_NICK_NAME_PREFIX;

/**
 * @author Y2014188432
 */
@Service
public class UserServerImpl extends ServiceImpl<UserMapper, User> implements UserServer {

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public Result getCode(String phone, HttpSession session) {
        // 1 判断手机号是否正确
        if (RegexUtils.isPhoneInvalid(phone)) {
            // 2 手机号错误返回错误信息
            return Result.fail("手机号不正确");
        }
        // 3 生成验证码
        String code = RandomUtil.randomNumbers(6);
        // 4 模拟发送验证码
        System.out.println("模拟发送验证码，验证码为 " + code);
        // 5 将验证码存入 redis 中,设置有效期为 1 分钟
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        // 6 返回
        return Result.ok();
    }

    @Override
    public Result loginByCode(String phone, String code) {
        // 1 判断手机号是否正确
        if (RegexUtils.isPhoneInvalid(phone)) {
            // 2 手机号错误返回错误信息
            return Result.fail("手机号不正确");
        }
        // 3 从 redis 中取验证码
        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
        // 4 若 redis 中无验证码，则为已过期
        if (cacheCode == null) {
            return Result.fail("验证码已过期");
        }
        // 5 若验证码不相符，则为验证码错误
        if(!cacheCode.equals(code)){
            return Result.fail("验证码错误");
        }
        // 6 从数据库内查询用户
        User user = query().eq("phone", phone).one();
        // 7 若无用户信息，创建一个新用户
        if (user == null) {
            user = createUser(phone);
        }
        // 8 创建 token，redis 缓存信息
        String token = createToken(user.getId());
        // 9 返回 token
        return Result.ok(token);
    }

    @Override
    public Result loginByPw(String phone, String password) {
        // 1 手机号格式错误返回错误
        if (RegexUtils.isPhoneInvalid(phone)) {
            return Result.fail("手机号不正确");
        }
        // 2 从数据库获取密码
        User user = query().eq("phone", phone).one();
        // 3 没有对应用户，返回错误
        if (user == null) {
            return Result.fail("账户不存在");
        }
        // 4 用户信息中密码为空，返回错误
        String encodingPassword = user.getPassword();
        if(encodingPassword == null){
            return Result.fail("无设置密码，请用验证码登录");
        }
        // 5 对比密码，对比失败返回错误
        if (!PasswordEncoder.matches(encodingPassword,password)) {
            return Result.fail("密码错误");
        }
        // 6 生成 token
        String token = createToken(user.getId());
        // 7 返回 token
        return Result.ok(token);
    }

    @Override
    public Result getMsg() {
        // 1 从 ThreadLocal 中取出用户 id
        String id = MyUtils.get();
        // 1-1 用户身份异常
        if(id == null){
            return Result.fail("未认证的用户");
        }
        // 2 根据用户 id 获得信息
        User user = getById(id);
        // 3 关键信息脱敏
        user.setPassword("");
        // 4 返回信息
        return Result.ok(user);
    }

    @Override
    public Result updateUser(User user) {
        // 1 从 threadLocal 中获得 id
        String strId = MyUtils.get();
        // 2 将 id 存入 user 中
        user.setId(Long.valueOf(strId));
        // 3 提出 user 的 birthday
        String birthday = user.getBirthday();
        // 4 birthday 非空转码
        if (birthday != null) {
            // 4-1 将 birthday 转为 yyyy-MM-DD 格式
            String substring = birthday.substring(0,10);
            // 4-2 重新存入 user
            user.setBirthday(substring);
        }
        // 5 执行更新
        updateById(user);
        // 6 返回结果
        return Result.ok();
    }

    @Override
    public Result updatePassword(String password, String passwordNew) {
        // 1 从 ThreadLocal 中获得用户 id
        String id = MyUtils.get();
        // 2 根据 id 从数据库中获得用户信息
        User user = getById(id);
        // 3 获得用户密码
        String passwordTrue = user.getPassword();
        // 3-1 若用户密码为空，则创建密码
        if (passwordTrue == null) {
            // 3-2 进行加密
            String encode =  PasswordEncoder.encode(passwordNew);
            // 3-3 存入用户
            user.setPassword(encode);
            // 3-4 写回数据库
            updateById(user);
            // 3-5 返回结果
            return Result.ok("成功创建了密码");
        }
        // 4 进行比对,不一致返回错误信息
        if (!PasswordEncoder.matches(passwordTrue,password)) {
            return Result.fail("密码错误");
        }
        // 5 将密码进行加密
        String encodePassword = PasswordEncoder.encode(passwordNew);
        // 6 将新密码写入 user 中
        user.setPassword(encodePassword);
        // 7 写回数据库
        updateById(user);
        // 8 返回结果
        return Result.ok("更新密码成功");
    }

    @Override
    public Result getMessageById(String id) {
        System.out.println("id = " + id);
        // 1 查数据库
        User userCache = getById(id);
        // 2 新建一个 user
        User user = new User();
        // 3 装载 ico
        user.setIco(userCache.getIco());
        // 4 装载 昵称
        user.setName(userCache.getName());
        // 5 返回
        return Result.ok(user);
    }

    @Override
    public Result getUserByPower() {
        // 0 power 为 00 是申请认证用户
        String power = "00";
        // 1 查表
        List<User> userList = query().eq("power", power).list();
        // 2 返回
        return Result.ok(userList);
    }

    @Override
    public Result changePower(User user) {
        updateById(user);
        return Result.ok();
    }

    /**
     * 创建一个 token，redis中存入用户 id
     * @param id 用户id
     * @return 一个token
     */
    public String createToken(Long id){
        // 1 使用 UUID 创建 Token
        String token = UUID.randomUUID().toString(true);
        // 2 将用户 id 存入到 redis 中
        stringRedisTemplate.opsForValue().set(LOGIN_TOKEN+token, String.valueOf(id));
        // 3 设置有效期为 30 分钟
        stringRedisTemplate.expire(LOGIN_TOKEN+token,LOGIN_TOKEN_TTL,TimeUnit.MINUTES);
        // 4 返回 token
        return token;
    }

    /**
     * 创建一个默认配置的新用户并保存到数据库
     * @param phone 手机号 (必填)
     * @return 新用户在数据库中的信息
     */
    public User createUser(String phone){
        // 1 新建一个 user 对象
        User user = new User();
        // 2 设置默认权限为 0
        user.setPower("0");
        // 3 添加手机号到 user
        user.setPhone(phone);
        // 4 随机生成用户名
        user.setName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));
        // 5 保存到数据库中
        System.out.println("user = " + user);
        save(user);
        // 6 根据手机号读出已保存的新用户信息（主要获得其 id）
        User userNew = query().eq("phone", phone).one();
        // 7 返回已保存的用户信息
        return userNew;
    }



}
